package org.example.hotel.service;

import jakarta.annotation.PostConstruct;
import org.example.hotel.config.SystemStatus;
import org.example.hotel.dto.RoomStatusDTO;
import org.example.hotel.dto.TotalCostDTO;
import org.example.hotel.entity.CheckinRecord;
import org.example.hotel.entity.Room;
import org.example.hotel.entity.UsageRecord;
import org.example.hotel.entity.Room.WindSpeed;
import org.example.hotel.repository.CheckinRecordRepository;
import org.example.hotel.repository.RoomRepository;
import org.example.hotel.repository.UsageRecordRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class RoomControlService {

    @Autowired
    private ScheduleService scheduleService;

    @Autowired
    private RoomRepository roomRepository;

    @Autowired
    private UsageRecordRepository recordRepository;

    @Autowired
    private CheckinRecordRepository checkinRecordRepository;

    @Autowired
    private SystemStatus systemStatus;

    public UsageRecord getLiveUsagePreview(int roomId) {
        return scheduleService.getLiveUsagePreview(roomId);
    }

    private final Map<Integer, LocalDateTime> acStartTimeMap = new HashMap<>();

    public void startAc(int roomId) {
        if (!systemStatus.isSystemRunning()) {
            throw new RuntimeException("系统已关闭，无法开启空调");
        }

        Room room = getRoom(roomId);
        room.setAcOn(true);
        if (room.getTargetTemp() == null) {
            room.setTargetTemp(25.0);
        }
        //room.setFanSpeed("LOW");
        //room.setServing(true);
        room.setLastSpeedChangeTime(LocalDateTime.now());
        roomRepository.save(room);

        //acStartTimeMap.put(roomId, LocalDateTime.now());
        scheduleService.processWindRequest(roomId, room.getWindSpeedEnum());
    }

    public void stopAc(int roomId) {
        Room room = getRoom(roomId);
        if (!room.isAcOn()) return;

        // 关闭空调开关
        room.setAcOn(false);
        roomRepository.save(room);

        // 统一释放服务、保存费用记录等交由调度服务处理
        scheduleService.releaseRoom(roomId);
    }


    public void setTargetTemp(int roomId, double temp) {
        Room room = getRoom(roomId);
        if (!room.isAcOn()) throw new RuntimeException("请先开启空调");

        String mode = room.getWorkMode();
        if (mode == null) throw new RuntimeException("请先设置工作模式（COLD 或 HOT）");

        if (mode.equalsIgnoreCase("COLD") && (temp < 18 || temp > 25)) {
            throw new IllegalArgumentException("制冷模式下可设置温度范围为18-25度");
        } else if (mode.equalsIgnoreCase("HOT") && (temp < 25 || temp > 30)) {
            throw new IllegalArgumentException("制热模式下可设置温度范围为25-30度");
        }

        room.setTargetTemp(temp);
        roomRepository.save(room);
    }

    public void setFanSpeed(int roomId, String speed) {
        Room room = getRoom(roomId);
        if (!room.isAcOn()) throw new RuntimeException("请先开启空调");

        WindSpeed newSpeed = WindSpeed.valueOf(speed.toUpperCase());
        LocalDateTime now = LocalDateTime.now();

        if (room.getLastSpeedChangeTime() != null &&
                Duration.between(room.getLastSpeedChangeTime(), now).toMillis() < 1000) {
            return; // 防抖
        }

        // 如果正在送风，且风速变了，先释放旧服务并计费
        if (room.isServing() && !room.getFanSpeed().equalsIgnoreCase(speed)) {
            scheduleService.releaseRoom(roomId); // 会自动保存 UsageRecord
        }

        room.setFanSpeed(speed);
        room.setLastSpeedChangeTime(now);
        roomRepository.save(room);

        // 设置新的送风起始时间并请求调度
        acStartTimeMap.put(roomId, now);
        scheduleService.processWindRequest(roomId, newSpeed);
    }

    public void setWorkMode(int roomId, String mode) {
        Room room = getRoom(roomId);
        if (!room.isAcOn()) throw new RuntimeException("请先开启空调");

        if (!mode.equalsIgnoreCase("COLD") && !mode.equalsIgnoreCase("HOT")) {
            throw new IllegalArgumentException("无效的工作模式，应为 COLD 或 HOT");
        }

        room.setWorkMode(mode.toUpperCase());

        if (mode.equalsIgnoreCase("COLD")) {
            if (room.getTargetTemp() == null || room.getTargetTemp() > 25 || room.getTargetTemp() < 18) {
                room.setTargetTemp(25.0);
            }
        } else {
            if (room.getTargetTemp() == null || room.getTargetTemp() < 25 || room.getTargetTemp() > 30) {
                room.setTargetTemp(25.0);
            }
        }

        roomRepository.save(room);
    }

    public RoomStatusDTO getRoomStatus(int roomId) {
        Room room = getRoom(roomId);
        double roundedCurrentTemp = Math.round(room.getCurrentTemp() * 100.0) / 100.0;
        return new RoomStatusDTO(
                room.getRoomId(),
                roundedCurrentTemp,
                room.getTargetTemp(),
                room.getFanSpeed(),
                room.isServing(),
                room.isAcOn(),
                room.getWorkMode(),
                0
        );
    }

    private Room getRoom(int roomId) {
        return roomRepository.findById(roomId)
                .orElseThrow(() -> new RuntimeException("房间不存在"));
    }

    // 系统启动时调用房费计算逻辑
    public void initRoomChargesOnStartup() {
        List<CheckinRecord> ongoingStays = checkinRecordRepository.findByCheckoutTimeIsNull();
        LocalDateTime now = LocalDateTime.now();

        for (CheckinRecord record : ongoingStays) {
            LocalDateTime checkinTime = record.getCheckinTime();
            long days = Duration.between(checkinTime, now).toDays();
            if (days < 1) days = 1;
            record.setRoomCost(days * 200.0);
            checkinRecordRepository.save(record);
        }

        System.out.println("[系统启动] 根据入住时间更新了房费，共计：" + ongoingStays.size() + "条记录。");
    }

    /*
    // 原来的每天中午定时任务
    @Scheduled(cron = "0 0 12 * * ?")
    public void applyDailyRoomCharge() {
        List<CheckinRecord> ongoingStays = checkinRecordRepository.findByCheckoutTimeIsNull();

        for (CheckinRecord record : ongoingStays) {
            record.setRoomCost(record.getRoomCost() + 200.0);
            checkinRecordRepository.save(record);
        }

        System.out.println("[定时任务] 已为入住中的房间增加200元房费，共计：" + ongoingStays.size() + "条记录。");
    }
    */



    public TotalCostDTO getCurrentTotalCost(int roomId) {
        try {
            CheckinRecord checkin = checkinRecordRepository.findByRoomIdAndCheckoutTimeIsNull(roomId)
                    .orElseThrow(() -> new RuntimeException("未找到该房间的入住记录"));
            double roomCost = checkin.getRoomCost();
            LocalDateTime checkinTime = checkin.getCheckinTime();

            List<UsageRecord> usageRecords = recordRepository.findByRoomId(roomId);
            double settledCost = usageRecords.stream()
                    .filter(record -> !record.getStartTime().isBefore(checkinTime))
                    .mapToDouble(UsageRecord::getCost)
                    .sum();

            double currentCost = 0.0;
            UsageRecord liveRecord = getLiveUsagePreview(roomId);
            if (liveRecord != null && !liveRecord.getStartTime().isBefore(checkinTime)) {
                currentCost = liveRecord.getCost();
            }

            double totalAcCost = settledCost + currentCost;
            double totalCost = roomCost + totalAcCost;
            return new TotalCostDTO(roomId, roomCost, totalAcCost, totalCost);
        } catch (RuntimeException e) {
            return new TotalCostDTO(roomId, 0.0, 0.0, 0.0);
        }
    }

    @PostConstruct
    public void restoreAcStartTimes() {
        List<Room> servingRooms = roomRepository.findAll().stream()
                .filter(room -> room.isAcOn() && room.isServing())
                .toList();

        for (Room room : servingRooms) {
            int roomId = room.getRoomId();
            LocalDateTime lastStart = room.getServiceStartTime();

            if (lastStart != null) {
                acStartTimeMap.put(roomId, lastStart);
                System.out.printf("[恢复] 房间 #%d 的送风起始时间恢复为 %s\n", roomId, lastStart);
            } else {
                System.out.printf("[警告] 房间 #%d 正在送风，但未记录 serviceStartTime，无法恢复\n", roomId);
            }
        }

        System.out.println("[启动恢复] 已恢复 " + servingRooms.size() + " 个房间的送风时间。");
    }


}

